#include "data_center/data_center.h"
#include "list/list.h"
#include "memory/memory.h"
#include "pico/mutex.h"


#ifdef __cplusplus
extern "C" {
#endif


#define DATA_CENTER_USER_MSG_CAPACITY           10  ///< 数据中心用户消息队列容量


/**
 * TDataCenterMsgManager 瑞驰N91 OTA公共消息管理结构体
 */
struct TDataCenterMsgManagerTag
{
    Bool         is_init_;      ///< 是否初始化
    TList_handle list_handle_;  ///< 消息列表句柄
    mutex_t      list_lock_;    ///< 消息列表锁
};
typedef struct TDataCenterMsgManagerTag TDataCenterMsgManager;

static TDataCenterMsgManager data_center_manager_[kMpuOtaMsgUserMax];

#define IsHandleValid(handle)   (handle >= 0 && handle < kMpuOtaMsgUserMax)


/**
 * @brief 初始化单个用户
 *
 * @param handle 访问句柄，详见 TDataCenterUser
 */
void TDataCenterInit(TDataCenterUser handle)
{
    if (IsHandleValid(handle))
    {
        TDataCenterMsgManager *self = &data_center_manager_[handle];

        if (! self->is_init_)
        {
            self->list_handle_ = TListCreate();
            mutex_init(&self->list_lock_);
            self->is_init_ = True;
        }
    }
}

/**
 * @brief 去初始化单个用户
 *
 * @param handle 访问句柄，详见 TDataCenterUser
 */
void TDataCenterFini(TDataCenterUser handle)
{
    if (IsHandleValid(handle))
    {
        TDataCenterMsgManager *self = &data_center_manager_[handle];

        if (self->is_init_)
        {
            Int32 item_idx = 0;

            self->is_init_ = False;

            TListDestroy(self->list_handle_);
            self->list_handle_ = -1;
        }
    }
}

/**
 * @brief 创建交互消息，内含内存申请
 *
 * @param content_size 附加内存长度
 * @return TDataCenterMsg* 返回的消息，为NULL则内存申请失败
 */
TDataCenterMsg* TDataCenterCreateMsg(UInt16 content_size)
{
    return (TDataCenterMsg *)MyMalloc(sizeof(TDataCenterMsg) + content_size);
}

/**
 * @brief 销毁交互消息，内含内存释放
 *
 * @param msg_t 待销毁消息结构体
 */
void TDataCenterDestroyMsg(TDataCenterMsg *msg_t)
{
    MyFree((void *)msg_t);
}

/**
 * @brief 发送交互消息，外部申请空间
 *
 * @param handle 访问句柄，详见 TDataCenterUser
 * @param msg_t 待发送消息结构体
 * @return Int32 >=0 发送成功，返回列表内下标，<0 发送失败
 */
Int32 TDataCenterSendMsg(TDataCenterUser handle, TDataCenterMsg *msg_t)
{
    Int32 ret = -1;

    if (msg_t != NULL && IsHandleValid(msg_t->receiver))
    {
        TDataCenterMsgManager *self = &data_center_manager_[msg_t->receiver];

        if (self->is_init_)
        {
            mutex_enter_blocking(&self->list_lock_);
            Int32 item_cnt = TListItemCount(self->list_handle_);

            if (item_cnt >= DATA_CENTER_USER_MSG_CAPACITY)
            {
                for (Int32 idx = 0; idx <= item_cnt - DATA_CENTER_USER_MSG_CAPACITY; idx ++)
                {
                    void *item = TListPop(self->list_handle_);

                    MyFree(item);
                }
            }

            ret = TListPush(self->list_handle_, (void *)msg_t);

            mutex_exit(&self->list_lock_);
        }
    }

    return ret;
}

/**
 * @brief 获取交互消息，但不取出
 *
 * @param handle 访问句柄，详见 TDataCenterUser
 * @return TDataCenterMsg* NULL 表示没有消息，否则返回消息结构体
 */
TDataCenterMsg* TDataCenterPeekMsg(TDataCenterUser handle)
{
    TDataCenterMsg* ret = NULL;

    if (IsHandleValid(handle))
    {
        TDataCenterMsgManager *self = &data_center_manager_[handle];

        if (self->is_init_)
        {
            mutex_enter_blocking(&self->list_lock_);

            ret = (TDataCenterMsg *)TListPeek(self->list_handle_);

            mutex_exit(&self->list_lock_);
        }
    }

    return ret;
}

/**
 * @brief 获取交互消息，并取出，外部释放空间
 *
 * @param handle 访问句柄，详见 TDataCenterUser
 * @return TDataCenterMsg* NULL 表示没有消息，否则返回消息结构体
 */
TDataCenterMsg* TDataCenterPopMsg(TDataCenterUser handle)
{
    TDataCenterMsg* ret = NULL;

    if (IsHandleValid(handle))
    {
        TDataCenterMsgManager *self = &data_center_manager_[handle];

        if (self->is_init_)
        {
            mutex_enter_blocking(&self->list_lock_);

            ret = (TDataCenterMsg *)TListPop(self->list_handle_);

            mutex_exit(&self->list_lock_);
        }
    }

    return ret;
}

#ifdef __cplusplus
} // extern "C" {
#endif
